﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "IDbObject.h"
#include "GcmpModelInterface.h"
#include "RegenDataId.h"

namespace gcmp
{
    class IElement;
    class IElementParentReporter;
    class ICalculatorCollection;
    class ICopyContext;
    class ICopyStrategyReporter;
    class IDocument;
    class IGraphicsElementShape;

    /// \brief 自定义几何关系基类
    class GCMP_MODEL_INTERFACE_EXPORT IGeometryRelationship : public IDbObject
    {
        DEFINE_CAST_DERIVED(gcmp::IGeometryRelationship, gcmp::IDbObject);

    public:
        /// \brief 析构器
        virtual ~IGeometryRelationship();

    public:
        /// \brief 设置该行为所属Element
        /// \param pOwnerElement 所属Element
        /// \return bool
        virtual bool SetOwnerElement(IElement* pOwnerElement) = 0;

        /// \brief 获得该行为所属的Element
        /// \return 所属的Element
        virtual IElement* GetOwnerElement() = 0;

        /// \brief 获得该行为所属的Element
        /// \return 所属的Element
        virtual const IElement* GetOwnerElement() const = 0;

        /// \brief 获得该行为产生的图形表达数据
        /// \return 返回图形表达指针
        virtual const IGraphicsElementShape* GetGraphicsElementShape() const = 0;

        /// \brief 获得该行为产生的图形表达数据
        /// \return 返回图形表达指针
        virtual IGraphicsElementShape* GetGraphicsElementShape() = 0;

        /// \brief 设置该行为产生的图形表达数据
        virtual void SetGraphicsElementShape(OwnerPtr<IGraphicsElementShape> opGraphicsElementShape) = 0;

        /// \brief 获得该行为运算优先级，数字越小，优先级越高
        /// \return 返回优先级
        virtual int GetPriority() const = 0;

#pragma region 关联更新
    public:
        /// \brief 报告依赖的ElementIds。对象删除和关联更新依赖于这个接口的正确实现。
        /// \param reporter 报告接口
        /// \return void
        virtual void ReportParents(IElementParentReporter& reporter) const = 0;

        /// \brief 外部用户报告自己定制的计算器
        ///
        /// GetCalculators中需要调用ICalculatorCollection::AddCalculator(OwnerPtr<ICalculator>)将计算器注册到ICalculatorCollection中。
        /// 若配合ADD_CALCULATOR宏使用，用户重写此方法时形参名也需使用“calculators”。
        /// \param calculators 计算器收集器指针
        /// \return void
        virtual void GetCalculators(ICalculatorCollection* calculators) const = 0;

        /// \brief 获取几何关系的RegenDataId
        /// \return 几何关系的RegenDataId
        virtual RegenDataId GetGeometryRelationshipRdId() const = 0;

        /// \brief 标记几何关系的RegenDataId，一般在SetGraphicsElementShape里面调用
        virtual void MarkGeometryRelationshipRdId() = 0;
#pragma endregion

#pragma region 复制粘贴
    public:
        /// \brief 报告引用的Element的id为拷贝、保持、放弃
        /// \param copyContext 拷贝上下文
        /// \param reporter 拷贝策略报告器
        /// \return void
        /// \see ICopyStrategyReporter
        virtual void Report(const ICopyContext & copyContext, ICopyStrategyReporter& reporter) const = 0;

        /// \brief 当Weak Parent被拷贝但此Element没有同时被拷贝时，此函数被调用
        ///
        /// 调用时机：当Weak Parent被拷贝但此Element没有同时被拷贝时，此Element会通过此接口收到通知。 
        /// 用途：一般用来处理Element存在Id容器的情况。 
        /// 例子：当Sketch里的对象被拷贝但Sketch本身没被拷贝时，Sketch通过实现此接口将拷贝的新对象加到SketchObjectId容器中。 
        ///
        /// \param pDocumentFrom 源文档
        /// \param pSource 被拷贝的IElement指针
        /// \param pCopy 拷贝得到的IElement指针
        /// \return void
        virtual void UpdateForWeakParentCopied(const IDocument* pDocumentFrom, const IElement* pSource, const IElement* pCopy) const = 0;
#pragma endregion

#pragma region 删除
    public:
        /// \brief 当弱依赖的Element被删除后，此接口会被调用。
        /// \param deleteElementIds 表示将被删除的Element ids
        /// \return void
        virtual void UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds) = 0;
#pragma endregion

#pragma region 消隐
    public:
        /// \brief 获取所有要与当前元素做消隐的ElementId
        /// \return 所有要与当前元素做消隐的ElementId
        virtual const std::set<ElementId> GetElementIdsToHideEdge() const = 0;
#pragma endregion

    };
}

